import main from "./index";
import { Gete } from "./utils";
import { IData } from "./models";

export default class {
  Dom: HTMLCanvasElement;
  Box: HTMLDivElement;
  private wrap: HTMLDivElement;
  private beginSize = { width: 256, height: 256 };
  private gap = 2;
  Control = { left: 0, top: 0, fromIndex: 0 };
  
  constructor() {
    this.Dom = Gete("outputCanvas") as HTMLCanvasElement;
    this.Dom.onclick = e => this.click(e);
    this.Dom.onkeydown = ({ key }) => {
      if (key !== "Delete") return;
      if (this.Box.hidden) return;
      
      const { CurrentIndex } = main.ObjList;
      if (CurrentIndex >= 0) main.Marker.Remove(CurrentIndex);
    };
    
    this.Box = Gete("selectBox") as HTMLDivElement;
    this.Box.onkeydown = ({ key }) => {
      if (key !== "Delete") return;
      
      const { CurrentIndex } = main.ObjList;
      if (CurrentIndex >= 0) main.Marker.Remove(CurrentIndex);
    };
    this.wrap = Gete("outputWrap") as HTMLDivElement;
    this.wrap.onscroll = () => this.BoxShow();
    const { width, height } = this.beginSize;
    this.setCanvasSize(width, height);
  }
  
  private setCanvasSize(width: number, height: number) {
    this.Dom.width = width;
    this.Dom.height = height;
    this.wrap.style.flex =
      width <= this.beginSize.width * 2 ? "unset" : "1";
  }
  
  DrawImage(markerIndex: number) {
    const cw = this.Dom.width, ch = this.Dom.height;
    let markerItem =
      main.Marker.Data[markerIndex ? markerIndex - 1 : markerIndex]; // 上一个精灵
    let sw = markerItem.width, sh = markerItem.height;
    if (markerIndex) this.Control.left += sw + this.gap;
    
    markerItem = main.Marker.Data[markerIndex]; // 当前精灵
    sw = markerItem.width;
    if (this.Control.left > cw - sw) {
      let maxHeight = 0;
      for (let i = this.Control.fromIndex; i < markerIndex; i += 1) {
        markerItem = main.Marker.Data[i];
        sh = markerItem.height;
        if (sh > maxHeight) maxHeight = sh;
      }
      this.Control.top += maxHeight + this.gap; // 换行，另起一行。
      this.Control.left = 0;
      this.Control.fromIndex = markerIndex;
    }
    if (this.Control.top > ch - sh) {
      // 对象超出画布了，扩展2倍尺寸。
      this.setCanvasSize(cw + cw, ch + ch);
      this.Update();
      return;
    }
    
    markerItem = main.Marker.Data[markerIndex];
    sw = markerItem.width;
    sh = markerItem.height;
    const { sprite } = markerItem;
    const { left, top } = this.Control;
    markerItem.output = { left, top };
    const { FileName } = main.FileList;
    const { canvas } = main.Canvas.Data[FileName] as IData;
    const ct = this.Dom.getContext("2d");
    ct.drawImage(
      canvas, // 原图
      sprite.left, sprite.top, sw, sh, // 原图位置和尺寸
      left, top, sw, sh, // 目标画布位置和尺寸
    );
  }
  
  Update() {
    if (main.Marker.Data.length) {
      // 略微抖动一下即可清除画布内容！
      this.Dom.width--;
      this.Dom.width++;
    } else {
      const { width, height } = this.beginSize;
      this.setCanvasSize(width, height);
    }
    
    // 清零
    this.Control.left = 0;
    this.Control.top = 0;
    this.Control.fromIndex = 0;
    
    for (let i = 0; i < main.Marker.Data.length; i += 1)
      this.DrawImage(i);
  }
  
  BoxHide() {
    this.Box.hidden = true;
  }
  
  BoxShow(left = 0, top = 0, width = 0, height = 0) {
    const { Box } = this;
    Box.hidden = false;
    const { offsetLeft, offsetTop, scrollLeft, scrollTop } = this.wrap;
    if (width) {
      // 来源于：objImg.onclick
      left += offsetLeft;
      top += offsetTop;
      let leftFix = left - scrollLeft, widthFix = width;
      let topFix = top - scrollTop, heightFix = height;
      if (leftFix < offsetLeft) {
        widthFix -= offsetLeft - leftFix;
        leftFix = offsetLeft;
      }
      if (topFix < offsetTop) {
        heightFix -= offsetTop - topFix;
        topFix = offsetTop;
      }
      Box.style.left = leftFix + "px";
      Box.style.top = topFix + "px";
      Box.style.width = widthFix + "px";
      Box.style.height = heightFix + "px";
      Box.title = "宽：" + width + "，高：" + height;
      // 数据备份
      Box["left"] = left;
      Box["top"] = top;
      Box["width"] = width;
      Box["height"] = height;
      return;
    }
    
    // 来源于：outputWrap.onscroll
    let leftFix = Box["left"] - scrollLeft, widthFix = Box["width"];
    let topFix = Box["top"] - scrollTop, heightFix = Box["height"];
    if (leftFix < offsetLeft) {
      widthFix -= offsetLeft - leftFix;
      leftFix = offsetLeft;
    }
    if (topFix < offsetTop) {
      heightFix -= offsetTop - topFix;
      topFix = offsetTop;
    }
    Box.style.left = leftFix + "px";
    Box.style.top = topFix + "px";
    Box.style.width = widthFix + "px";
    Box.style.height = heightFix + "px";
  }
  
  private click(e: MouseEvent) {
    const mx = e.offsetX, my = e.offsetY;
    
    // 检查点击位置，若点击到精灵则选中它。
    for (let i = 0; i < main.Marker.Data.length; i += 1) {
      const markerItem = main.Marker.Data[i];
      const { width, height, output } = markerItem;
      const { left, top } = output;
      if (mx >= left && my >= top && mx < left + width && my < top + height) {
        main.ObjList.SetCurrent(i); // 点中了一个精灵，则选中它。
        main.ObjList.Dom.scrollTop = i * 51;
        break;
      }
    }
  }
  
  SwitchMode() {
    const { IsTest } = main.Toolbar;
    if (IsTest) {
      if (this.Box.hidden && main.Marker.Data.length > 0)
        main.ObjList.SetCurrent(0);
    }
  }
};
